package cn.itcast.order.quartz;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.quartz.spi.JobFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
public class DBQuartzConfig {

    // spring配置的数据源信息
    @Autowired
    private DataSource dataSource;

    @Autowired
    private QuartzApplication quartzApplication;

    @Bean
    public JobFactory jobFactory() {
        return new SpringBeanJobFactory();
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws Exception {
        // SchedulerFactoryBean是Spring框架提供的一个工厂Bean，用于创建和配置Quartz调度器
        /**
         * 功能与作用
         *
         * 创建和配置Quartz调度器：SchedulerFactoryBean负责创建Quartz调度器实例，并根据配置进行适当的初始化。
         * 注册作业和触发器：它创建并配置JobDetail（定义具体任务）和Trigger（定义任务的触发条件），然后将它们注册到Quartz调度器中。
         * 管理调度任务：一旦调度器启动，它将根据Trigger的触发条件自动触发并执行对应的Job。
         * 此外，SchedulerFactoryBean还提供了一些方法，用于对Quartz调度器进行操作，如暂停、恢复、删除任务等。
         */
        SchedulerFactoryBean factory = new SchedulerFactoryBean();

        // 配置Quartz Scheduler的属性
        Properties properties = new Properties();

        // Scheduler实例的名称
        properties.put("org.quartz.scheduler.instanceName", "MyClusteredScheduler");
        // Scheduler实例的ID，AUTO表示自动生成
        properties.put("org.quartz.scheduler.instanceId", "AUTO");
        // 触发器的失火阈值，单位为毫秒。如果任务在这个时间范围内没有触发，则认为是失火
        properties.put("org.quartz.jobStore.misfireThreshold", "60000");
        // JobStore的实现类，使用JDBCJobStore来存储作业和触发器的信息
        properties.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
        // 数据库驱动的代理类，根据使用的数据库选择合适的代理类，换成psql，需要改PostgreSQLDelegate
        properties.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
        // 是否以属性文件的方式来存储作业和触发器的信息，false表示使用数据库存储
        properties.put("org.quartz.jobStore.useProperties", "false");
        // 指定JobStore使用的数据源
        properties.put("org.quartz.jobStore.dataSource", "myDS");
        // Quartz表的前缀，默认为QRTZ_
        properties.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        // 是否为集群模式，true表示集群模式
        properties.put("org.quartz.jobStore.isClustered", "false");

        // 配置线程池
        // properties.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        // 线程池中的线程数量
        // properties.put("org.quartz.threadPool.threadCount", "10");
        // 线程池中线程的优先级
        // properties.put("org.quartz.threadPool.threadPriority", "5");

        // 配置数据源属性
        // 数据库驱动类名

        properties.put("org.quartz.dataSource.myDS.driver", quartzApplication.getDriverClassName());
        // 数据库URL
        properties.put("org.quartz.dataSource.myDS.URL", quartzApplication.getUrl());
        // 数据库用户名
        properties.put("org.quartz.dataSource.myDS.user", quartzApplication.getUsername());
        // 数据库密码
        properties.put("org.quartz.dataSource.myDS.password", quartzApplication.getUsername());
        // 数据源的最大连接数
        properties.put("org.quartz.dataSource.myDS.maxConnections", "5");
        // 用于验证数据库连接是否有效的SQL语句
        properties.put("org.quartz.dataSource.myDS.validationQuery", "select 1");

        // 将配置好的属性设置给SchedulerFactoryBean
        factory.setQuartzProperties(properties);
        factory.setJobFactory(jobFactory);
        // 设置数据源，这里的数据源应该是一个配置好的Bean，用于Quartz连接数据库
        factory.setDataSource(dataSource);
        // 关闭Scheduler时是否等待正在执行的任务5完成
        //如果调度器接收到关闭信号（例如，应用上下文被关闭），它将等待所有当前正在执行的任务完成后再关闭。
        // 这意味着，即使应用正在停止，已经启动的任务也会继续执行直到完成。
        factory.setWaitForJobsToCompleteOnShutdown(true);
        // 通过设置事务管理器，Quartz 能够支持在作业（Job）中执行事务性操作。
        // 这意味着，如果作业中的某个操作失败了，整个事务可以回滚，以确保数据的一致性。
        // 这对于执行数据库更新、插入或删除操作的作业特别重要。
        factory.setTransactionManager(new DataSourceTransactionManager(dataSource));
        // 是否覆盖已经存在的作业定义
//        factory.setOverwriteExistingJobs(true);

        return factory;
    }

    /**
     * http发送请求
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost postRequest = new HttpPost("http://127.0.0.1:8081/user/hello");



        /**
         * json格式
         */
        /*
        postRequest.setHeader("Content-Type", "application/json");
        String json = "[1,2]";
        StringEntity entity = new StringEntity(json);
        postRequest.setEntity(entity);*/

        /**
         * @RequstParam格式
         */
        /*
        postRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("name", "danhong"));
        params.add(new BasicNameValuePair("user", "hello"));

        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8);
        postRequest.setEntity(entity);*/

        CloseableHttpResponse response = httpClient.execute(postRequest);

        try {
            System.out.println("-------------------");
            System.out.println(EntityUtils.toString(response.getEntity()));
            System.out.println("-------------------");

        } finally {
            response.close();
            httpClient.close();
        }
    }
}